package com.zmn.oms.business.impl.servtype;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.price.common.dro.item.ItemAdditionDRO;
import com.zmn.base.price.common.dto.item.ItemDRO;
import com.zmn.base.price.dubbo.interfaces.item.ItemAdditionRemoteService;
import com.zmn.base.price.dubbo.interfaces.item.ItemRemoteService;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.dms.common.dto.promotion.dro.Meter3ArtificialPromDRO;
import com.zmn.dms.dubbo.interfaces.prom.Meter3ArtificialPromListRemoteService;
import com.zmn.oms.business.interfaces.servtype.ServItemBService;
import com.zmn.oms.common.dio.quotation3.ArtificialPromDRO;
import com.zmn.oms.common.enums.ServiceItemTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.work.modify.*;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.scm2.common.model.dro.BasePageDRO;
import com.zmn.scm2.common.model.dro.scm.engineer.warehouse.EngineerWarehouseDRO;
import com.zmn.scm2.dubbo.interfaces.scm.engineer.warehouse.EngineerWarehouseListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName AbstractServTypeDistributeService
 * @description: 服务类型处理入口
 * @author: wangyanci
 * @create: 2021-11-26 18:08
 * @Version 1.0
 **/
@Slf4j
public abstract class AbstractServItemService implements ServItemBService {

    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    protected EngineerWarehouseListRemoteService engineerWarehouseListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ProductForeignListRemoteService productForeignListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    protected ItemRemoteService itemRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    protected ItemAdditionRemoteService itemAdditionRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    protected Meter3ArtificialPromListRemoteService meter3ArtificialPromListRemoteService;


    @Override
    public ResponseDTO<ServiceItemResultDTO> getServiceItem(ServiceItemQueryDTO serviceItemQueryDTO) {
        log.info("AbstractServTypeDistributeService.getDefaultServiceItem serviceItemQueryDTO={}", JSON.toJSONString(serviceItemQueryDTO));
        return this.doGetServiceItem(serviceItemQueryDTO);
    }

    @Override
    public List<ServiceItemResultDTO> listServiceItem(ServiceItemQueryDTO serviceItemQueryDTO) {
        log.info("AbstractServTypeDistributeService.listServiceItem serviceItemQueryDTO={}", JSON.toJSONString(serviceItemQueryDTO));
        return this.doListServiceItem(serviceItemQueryDTO);
    }

    @Override
    public ResponseDTO<BasePageDRO<EngineerWarehouseDRO>> listPageEngineerWarehouseByQueryV2(PartQueryDTO partQueryDTO) throws OmsBaseException {
        log.info("AbstractServTypeDistributeService.listPageEngineerWarehouseByQueryV2 partQueryDTO={}", JSON.toJSONString(partQueryDTO));
        return this.doListPageEngineerWarehouseByQueryV2(partQueryDTO);
    }

    @Override
    public List<OrderServiceItem> filterServiceItem(List<OrderServiceItem> serviceItems, Integer servItemType, Integer finalPrice) {
        log.info("AbstractServItemService.filterServiceItem serviceItems={}", serviceItems);
        return this.doFilterServiceItem(serviceItems, servItemType, finalPrice);
    }

    @Override
    public BackProductPriceResultDTO queryBackProductPrice(BackProductPriceQueryDTO backProductPriceQueryDTO) {
        log.info("AbstractServItemService.queryBackProductPrice backProductPriceQueryDTO={}", backProductPriceQueryDTO);
        return this.doQueryBackProductPrice(backProductPriceQueryDTO);
    }

    @Override
    public List<Integer> getServItemTypeIdList(Integer servItemType) {
        return this.doQueryServItemTypeIdList(servItemType);
    }

    @Override
    public List<ArtificialPromDRO> listArtificialProm(Integer servItemType, ArtificialPromQueryDTO query) throws OmsBaseException {
        return this.doQueryArtificialPromList(query);
    }

    abstract List<OrderServiceItem> doFilterServiceItem(List<OrderServiceItem> serviceItems, Integer servItemType, Integer finalPrice);
    abstract ResponseDTO<BasePageDRO<EngineerWarehouseDRO>> doListPageEngineerWarehouseByQueryV2(PartQueryDTO partQueryDTO) throws OmsBaseException;
    abstract ResponseDTO<ServiceItemResultDTO> doGetServiceItem(ServiceItemQueryDTO serviceItemQueryDTO);
    abstract List<ServiceItemResultDTO> doListServiceItem(ServiceItemQueryDTO serviceItemQueryDTO);
    abstract BackProductPriceResultDTO doQueryBackProductPrice(BackProductPriceQueryDTO backProductPriceQueryDTO);
    abstract List<Integer> doQueryServItemTypeIdList(Integer servItemType);
    abstract List<ArtificialPromDRO> doQueryArtificialPromList(ArtificialPromQueryDTO query) throws OmsBaseException;


    protected Map<Integer, ProductBaseDRO> getProductBaseDROMap(List<Integer> productIds){
        ProductBaseQuery productBaseQuery = ProductBaseQuery
                .builder()
                .productIdList(productIds)
                .build();
        log.info("productForeignListRemoteService.listBaseDROByQuery productBaseQuery={}", productBaseQuery);
        ResponseDTO<List<ProductBaseDRO>> productResponseDTO = productForeignListRemoteService.listBaseDROByQuery(productBaseQuery);
        log.info("productForeignListRemoteService.listBaseDROByQuery productResponseDTO={}", productResponseDTO);
        if (!productResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(productResponseDTO.getData())) {
            return Maps.newHashMap();
        }
        return Maps.uniqueIndex(productResponseDTO.getData(), ProductBaseDRO::getProductId);
    }

    /**
     * 获取特殊服务项
     * @param idList
     * @return
     */
    protected List<ItemDRO> listSpecialItemByIdList(List<Integer> idList) {
        if (CollectionUtil.isNullOrEmpty(idList)) {
            return new ArrayList<>();
        }
        log.info("itemRemoteService.listSpecialItemByIdList idList={}", idList);
        ResponseDTO<List<ItemDRO>> listResponseDTO = itemRemoteService.listSpecialItemByIdList(idList);
        log.info("itemRemoteService.listSpecialItemByIdList listResponseDTO={}", listResponseDTO);
        if (!listResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return new ArrayList<>();
        }
        return listResponseDTO.getData();
    }

    /**
     * 获取附加服务项
     *
     * @param cityId
     * @param servCategId
     * @param categId
     * @return
     */
    protected List<ServiceItemResultDTO> listAdditionItemByCityAndCateg(Integer cityId, Integer servCategId, Integer categId, Integer servItemType) {
        log.info("itemAdditionRemoteService.listByCityAndCateg cityId={},servCategId={},categId={}", cityId, servCategId, categId);
        ResponseDTO<List<ItemAdditionDRO>> listResponseDTO = itemAdditionRemoteService.listByCityAndCateg(cityId, servCategId, categId);
        log.info("itemAdditionRemoteService.listByCityAndCateg listResponseDTO={}", listResponseDTO);
        if (!listResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return new ArrayList<>();
        }
        List<ItemDRO> itemDROList = new ArrayList<>(listResponseDTO.getData().size());

        List<ItemAdditionDRO> itemAdditionDROList = listResponseDTO.getData();
        // 计价器2.0 过滤掉 运杂费
//        if (Objects.equals(servItemType, OrderConsts.SERVICE_ITEM_TYPE_FAULT)) {
//            itemAdditionDROList = itemAdditionDROList.stream()
//                    .filter(e -> !Objects.equals(e.getItemAdditionId(), ItemAdditionConst.ADDITION_FREIGHT_ID))
//                    .collect(Collectors.toList());
//        }

        for (ItemAdditionDRO itemAdditionDRO : itemAdditionDROList) {
            ItemDRO itemDRO = new ItemDRO();
            itemDRO.setItemId(itemAdditionDRO.getItemAdditionId());
            itemDRO.setItemName(itemAdditionDRO.getItemAdditionName());
            itemDRO.setPrice(itemAdditionDRO.getPrice());
            itemDRO.setSort(itemAdditionDRO.getSort());
            itemDRO.setStatus(itemAdditionDRO.getStatus());
            itemDRO.setItemTypeId(ServiceItemTypeEnum.ADDITION_ITEM.getType());
            itemDRO.setItemTypeName(ServiceItemTypeEnum.ADDITION_ITEM.getName());
            itemDRO.setCategSort(ServiceItemTypeEnum.ADDITION_ITEM.getType());
            itemDRO.setItemStandard(GlobalConsts.NO);
            itemDRO.setEditPrice(Objects.isNull(itemAdditionDRO.getPrice()) ? GlobalConsts.YES : GlobalConsts.NO);
            itemDRO.setMaxOptionNumber(1);
            itemDRO.setClientShow(GlobalConsts.YES);
            itemDRO.setMutexMode(3);
            itemDRO.setHasDetail(GlobalConsts.NO);

            itemDROList.add(itemDRO);
        }

        List<ServiceItemResultDTO> serviceItemResultDTOList = this.itemDRO2ServiceItemResultDTO(itemDROList);
        Map<Integer, ItemAdditionDRO> itemAdditionDROMap = Maps.uniqueIndex(itemAdditionDROList, ItemAdditionDRO::getItemAdditionId);
        for (ServiceItemResultDTO dto : serviceItemResultDTOList) {
            ItemAdditionDRO itemAdditionDRO = itemAdditionDROMap.get(dto.getItemId());
            if (Objects.isNull(itemAdditionDRO)) {
                continue;
            }
            dto.setEndTime(itemAdditionDRO.getEndTime());
            dto.setBeginTime(itemAdditionDRO.getBeginTime());
        }


        return serviceItemResultDTOList;
    }


    /**
     * dro 转换 DTO
     * @param itemDROList
     * @return
     */
    protected List<ServiceItemResultDTO> itemDRO2ServiceItemResultDTO(List<ItemDRO> itemDROList){
        if (CollectionUtil.isNullOrEmpty(itemDROList)) {
            return new ArrayList<>();
        }
        List<ServiceItemResultDTO> serviceItemResultDTOList = Lists.newArrayListWithCapacity(itemDROList.size());
        for (ItemDRO itemTo : itemDROList) {
            ServiceItemResultDTO serviceItemResultDTO = ServiceItemResultDTO.builder()
//                    .servItemType(serviceItemQueryDTO.getServItemType())
                    .itemId(itemTo.getItemId())
                    .itemName(itemTo.getItemName())
                    .price(itemTo.getPrice())
                    .internalSettlementPrice(itemTo.getPriceInternalSettlement())
                    //当项目有配置：内部和外部价，则以配置的为准；当项目未配置时，则内部价=外部价=配件销售总额
                    .externalSettlementPrice(Optional.ofNullable(itemTo.getPriceExternalSettlement()).orElse(itemTo.getPrice()))
                    .tariffId(itemTo.getTariffId())
                    .unit(itemTo.getItemUnit())
                    .itemCategId(itemTo.getItemTypeId())
                    .itemCategName(itemTo.getItemTypeName())
                    .categSort(itemTo.getCategSort())
                    .priceStandard(itemTo.getItemStandard())
                    .general(itemTo.getDefaultSkuPrice())
                    .negotiableMaxPrice(itemTo.getPriceMax())
                    .negotiableMinPrice(itemTo.getPriceMin())
                    .countLimit(itemTo.getMaxOptionNumber())
                    .manualPrice(itemTo.getEditPrice())
                    .showPrice(itemTo.getClientShow())
                    .mutexMode(itemTo.getMutexMode())
                    .hasDetail(itemTo.getHasDetail())
                    .productName(itemTo.getProductName())
                    .productSort(itemTo.getProductSort())
                    .categId(itemTo.getCategId())
                    .build();
            if (CollectionUtil.isNotNullOrEmpty(itemTo.getItemCellList())) {
                List<ServiceItemDetailResultDTO> detailResultDTOList = itemTo.getItemCellList()
                        .stream()
                        .filter(e -> Objects.equals(e.getStatus(), com.zmn.common.constant.GlobalConsts.YES))
                        .map(e -> new ServiceItemDetailResultDTO(e.getItemCellId(), e.getItemCellName(), e.getCellPrice(), e.getSort()))
                        .collect(Collectors.toList());
                serviceItemResultDTO.setDetailResultDTOList(detailResultDTOList);
            }
            serviceItemResultDTOList.add(serviceItemResultDTO);
        }

        return serviceItemResultDTOList;
    }

    /**
     * 过滤服务项
     * @param serviceItemResultDTOS
     * @param serviceItemQueryDTO
     */
    protected void filterServiceItemByQuery(List<ServiceItemResultDTO> serviceItemResultDTOS, ServiceItemQueryDTO serviceItemQueryDTO) {
        if (CollectionUtil.isNullOrEmpty(serviceItemResultDTOS)) {
            return;
        }
        // 过滤服务项
        Iterator<ServiceItemResultDTO> iterator = serviceItemResultDTOS.iterator();
        while (iterator.hasNext()) {
            ServiceItemResultDTO serviceItemResultDTO = iterator.next();
            if (serviceItemQueryDTO.isFilterNullPrice()) {
                if (Objects.isNull(serviceItemResultDTO.getPrice())) {
                    iterator.remove();
                    continue;
                }
            }

            if (Objects.nonNull(serviceItemQueryDTO.getGeneral())) {
                if (!Objects.equals(serviceItemQueryDTO.getGeneral(), serviceItemResultDTO.getGeneral())) {
                    iterator.remove();
                    continue;
                }
            }

            if (Objects.nonNull(serviceItemQueryDTO.getPriceStandard())) {
                if (!Objects.equals(serviceItemQueryDTO.getPriceStandard(), serviceItemResultDTO.getPriceStandard())) {
                    iterator.remove();
                }
            }
        }
    }

    protected List<ArtificialPromDRO> meter3ArtificialPromDRO2ArtificialPromDRO(List<Meter3ArtificialPromDRO> promDROS) {
        if (CollectionUtil.isNullOrEmpty(promDROS)) {
            return Collections.EMPTY_LIST;
        }
        List<ArtificialPromDRO> list = new ArrayList(promDROS.size());
        for (Meter3ArtificialPromDRO meter3ArtificialPromDRO : promDROS) {
            ArtificialPromDRO artificialPromDRO = new ArtificialPromDRO();
            artificialPromDRO.setId(meter3ArtificialPromDRO.getId());
            artificialPromDRO.setName(meter3ArtificialPromDRO.getName());
            artificialPromDRO.setShowName(meter3ArtificialPromDRO.getShowName());
            artificialPromDRO.setBeginTime(meter3ArtificialPromDRO.getBeginTime());
            artificialPromDRO.setEndTime(meter3ArtificialPromDRO.getEndTime());
            artificialPromDRO.setAdvertising(meter3ArtificialPromDRO.getAdvertising());
            artificialPromDRO.setType(meter3ArtificialPromDRO.getType());
            artificialPromDRO.setMode(meter3ArtificialPromDRO.getMode());
            artificialPromDRO.setOrderAmount(meter3ArtificialPromDRO.getOrderAmount());
            artificialPromDRO.setReduce(meter3ArtificialPromDRO.getReduce());
            artificialPromDRO.setDiscount(meter3ArtificialPromDRO.getDiscount());
            artificialPromDRO.setMasterDiscount(meter3ArtificialPromDRO.getMasterDiscount());
            artificialPromDRO.setOperatorDiscount(meter3ArtificialPromDRO.getOperatorDiscount());
            list.add(artificialPromDRO);
        }

        return list;
    }
}